package com.chendx.store.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.chendx.model.cart.dto.CartDto;
import com.chendx.model.cart.vo.CartVo;
import com.chendx.model.cart.vo.PreferentialVo;
import com.chendx.model.common.dtos.ResponseResult;
import com.chendx.model.common.enums.AppHttpCodeEnum;
import com.chendx.model.goods.pojo.Pref;
import com.chendx.model.goods.pojo.Sku;
import com.chendx.model.goods.pojo.Spu;
import com.chendx.model.user.pojo.User;
import com.chendx.model.user.pojo.UserPref;
import com.chendx.store.common.constants.cart.CartConstants;
import com.chendx.store.common.constants.goods.GoodsConstants;
import com.chendx.store.order.feign.GoodsFeign;
import com.chendx.store.order.service.CartService;
import com.chendx.store.utils.AppThreadLocalUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by chendx on 2022/4/20.
 */
@Service
public class CartServiceImpl implements CartService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private GoodsFeign goodsFeign;

    public ResponseResult addCart(CartDto dto) {
        User user = AppThreadLocalUtils.get();
        if (user == null || user.getId() == null || user.getUsername() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        String username = user.getUsername();
        if (dto != null && !StringUtils.isEmpty(dto.getSkuId()) && !StringUtils.isEmpty(dto.getNum())) {

            Sku sku = this.goodsFeign.findSkuById(Long.valueOf(dto.getSkuId()));
            Object obj = this.redisTemplate.boundHashOps(CartConstants.USER_CART + username).get(dto.getSkuId());
            CartVo cartVo = null;
            if (obj != null) {
                cartVo = JSON.parseObject(String.valueOf(obj), CartVo.class);
            }
            if (sku == null) {
                this.redisTemplate.boundHashOps(CartConstants.USER_CART + username).delete(dto.getSkuId());
                return ResponseResult.errorResult(AppHttpCodeEnum.SKU_NOT_EXIST);
            } else {
                Spu spu = this.goodsFeign.findById(sku.getSpuId());
                if (spu == null) {
                    return ResponseResult.errorResult(AppHttpCodeEnum.SKU_NOT_EXIST);
                } else {
                    if (cartVo != null) {
                        cartVo.setNum(cartVo.getNum() + dto.getNum());
                        if (cartVo.getNum() <= 0) {
                            this.redisTemplate.boundHashOps(CartConstants.USER_CART + username).delete(dto.getSkuId());
                            return ResponseResult.errorResult(AppHttpCodeEnum.SKU_IS_DELETE);
                        }

                        cartVo.setMoney(sku.getPrice() * cartVo.getNum());
                        cartVo.setPayMoney(sku.getPrice() * cartVo.getNum());
                        cartVo.setWeight(sku.getWeight() * cartVo.getNum());
                    } else {
                        cartVo = new CartVo();
                        cartVo.setCategoryId1(spu.getCategory1Id());
                        cartVo.setCategoryId2(spu.getCategory2Id());
                        cartVo.setCategoryId3(spu.getCategory3Id());
                        cartVo.setSpuId(String.valueOf(spu.getId()));
                        cartVo.setSkuId(dto.getSkuId());
                        cartVo.setName(sku.getName());
                        cartVo.setPrice(sku.getPrice());
                        cartVo.setNum(dto.getNum());
                        cartVo.setMoney(sku.getPrice() * cartVo.getNum());
                        cartVo.setPayMoney(sku.getPrice() * cartVo.getNum());
                        cartVo.setWeight(sku.getWeight() * cartVo.getNum());
                        cartVo.setImage(sku.getImage());
                        cartVo.setChecked(true);
                        cartVo.setSpecMap(JSON.parseObject(sku.getSpec(), Map.class));
                    }

                    this.redisTemplate.boundHashOps(CartConstants.USER_CART + username).put(dto.getSkuId(), JSON.toJSONString(cartVo));
                    return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
                }
            }
        } else {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
    }

    public ResponseResult loadCart() {
        User user = AppThreadLocalUtils.get();
        if (user == null || user.getId() == null || user.getUsername() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        String username = user.getUsername();
        List<CartVo> cartVos =
                JSON.parseArray(String.valueOf(this.redisTemplate.boundHashOps(CartConstants.USER_CART + username).values()), CartVo.class);
        return ResponseResult.okResult(cartVos);
    }

    public ResponseResult updateChecked(CartDto dto) {
        User user = AppThreadLocalUtils.get();
        if (user == null || user.getId() == null || user.getUsername() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        String username = user.getUsername();
        if (dto != null && !StringUtils.isEmpty(dto.getSkuId())) {
            Object obj = this.redisTemplate.boundHashOps(CartConstants.USER_CART + username).get(dto.getSkuId());
            if (obj == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.SKU_IS_DELETE);
            } else {
                CartVo cartVo = JSON.parseObject(String.valueOf(obj), CartVo.class);
                cartVo.setChecked(dto.getChecked());
                this.redisTemplate.boundHashOps(CartConstants.USER_CART + username).put(dto.getSkuId(), JSON.toJSONString(cartVo));
                return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
            }
        } else {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
    }

    public ResponseResult deleteChecked() {
        User user = AppThreadLocalUtils.get();
        if (user == null || user.getId() == null || user.getUsername() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        String username = user.getUsername();
        ResponseResult responseResult = this.loadCart();
        if (responseResult.getData() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        } else {
            List<CartVo> cartList = (List<CartVo>) responseResult.getData();
            List<String> skuIds = cartList.stream()
                    .filter(cart -> cart.isChecked())
                    .map(cart -> String.valueOf(cart.getSkuId())).collect(Collectors.toList());
            if (skuIds != null && skuIds.size() > 0) {
                this.redisTemplate.boundHashOps(CartConstants.USER_CART + username).delete(skuIds.toArray());
            }

            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }
    }

    /**
     * 多个商品可使用的优惠券
     *
     * @param totalMoney
     * @return
     */
    public ResponseResult preferential(Integer totalMoney) {
        User user = AppThreadLocalUtils.get();
        if (user == null || user.getId() == null || user.getUsername() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        String username = user.getUsername();
        if (!StringUtils.isEmpty(Integer.valueOf(totalMoney)) && totalMoney >= 0) {
            List<Pref> okUsePref = new ArrayList<>();
            List<CartVo> carts = (List) this.loadCart().getData();
            List<CartVo> cartList = carts.stream().filter(cart -> cart.isChecked()).collect(Collectors.toList());
            Map<Integer, IntSummaryStatistics> cartMap = cartList.stream().collect(
                    Collectors.groupingBy(CartVo::getCategoryId3,
                            Collectors.summarizingInt(CartVo::getMoney)));

            int allPreMoney = 0;
            int preMoney = 0;
            Set<Object> keys = redisTemplate.boundHashOps(CartConstants.RECEIVER_PREF + username).keys();
            for (Integer categoryId : cartMap.keySet()) {
                int buyMoney = (int) cartMap.get(categoryId).getSum();
                for (Object object : keys) {
                    String key = String.valueOf(object);
                    Object obj = redisTemplate.boundHashOps(CartConstants.RECEIVER_PREF + username).get(key);
                    UserPref userPref = JSON.parseObject(String.valueOf(obj), UserPref.class);
                    if (userPref != null && userPref.getStatus().equals("0")) {
                        Object ob = this.redisTemplate.boundHashOps(GoodsConstants.PREF_COUPON).get(key);
                        if (ob == null) {
                            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
                        }
                        Pref pref = JSON.parseObject((String) ob, Pref.class);
                        if (pref.getCateId().equals(categoryId) && buyMoney >= pref.getBuyMoney()) {
                            preMoney += pref.getPreMoney();
                            okUsePref.add(pref);
                        }
                    }
                }
                allPreMoney += buyMoney;
            }
            PreferentialVo vo = new PreferentialVo();
            vo.setAllPreMoney(allPreMoney);
            vo.setPreMoney(preMoney);
            vo.setOkUsePref(okUsePref);
            return ResponseResult.okResult(vo);
        } else {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
    }

    @Override
    public ResponseResult orderPref(Integer totalMoney, Integer categoryId) {
        if (StringUtils.isEmpty(totalMoney) || totalMoney <= 0 || StringUtils.isEmpty(categoryId)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        User user = AppThreadLocalUtils.get();
        if (user == null || user.getId() == null || user.getUsername() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        String username = user.getUsername();
        List<Pref> okUsePref = new ArrayList<>();
        int allPreMoney = 0;
        int preMoney = 0;
        Set<Object> keys = redisTemplate.boundHashOps(CartConstants.RECEIVER_PREF + username).keys();
        for (Object obj : keys) {
            String key = String.valueOf(obj);
            UserPref userPref = JSON.parseObject(String.valueOf(redisTemplate.boundHashOps(CartConstants.RECEIVER_PREF + username).get(key)), UserPref.class);
            if (userPref.getStatus().equals("0")) {
                Object ob = this.redisTemplate.boundHashOps(GoodsConstants.PREF_COUPON).get(key);
                if (ob == null) {
                    return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
                }
                Pref pref = JSON.parseObject((String) ob, Pref.class);
                if (pref.getCateId().equals(categoryId) && totalMoney >= pref.getBuyMoney()) {
                    preMoney += pref.getPreMoney();
                    okUsePref.add(pref);
                }
            }
        }
        PreferentialVo vo = new PreferentialVo();
        vo.setAllPreMoney(allPreMoney);
        vo.setPreMoney(preMoney);
        vo.setOkUsePref(okUsePref);
        return ResponseResult.okResult(vo);
    }

    @Override
    public ResponseResult loadCheckedCartList() {
        User user = AppThreadLocalUtils.get();
        if (user == null || user.getId() == null || user.getUsername() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        String username = user.getUsername();
        List<CartVo> cartVos =
                JSON.parseArray(String.valueOf(this.redisTemplate.boundHashOps(CartConstants.USER_CART + username).values()), CartVo.class);

        List<CartVo> checkCartVos = new ArrayList<>();
        checkCartVos = cartVos.stream().filter(cart -> cart.isChecked()).collect(Collectors.toList());
        return ResponseResult.okResult(checkCartVos);
    }
}
